--- author:liushiyin
--- date: 2019-10-29 15:20:17
--- des: #des#
local ViewBase = require("app.ui.ViewBase")
local CommonScrollBar = class("CommonScrollBar", ViewBase)

CommonScrollBar.DIR_VERTICAL = 1
CommonScrollBar.DIR_HORIZENTAL = 2

function CommonScrollBar:ctor(targetView, dir, csb)
	local filecsb = csb or Path.getCSB("CommonScrollBar", "package")
	local resource = {
		file = filecsb,
		binding = {}
	}
	self._pTarget = targetView
	self._direction = dir
	self._ratio = 0.0
	CommonScrollBar.super.ctor(self, resource)
end

function CommonScrollBar:onCreate()
	self._preContentSize = self._pTarget:getInnerContainerSize()
	self._viewSize = self._pTarget:getContentSize()
	if self._direction == CommonScrollBar.DIR_VERTICAL then
		self._barBg:setPosition(cc.p(0, 0))
		self._pSlider:setPositionX(0)
	elseif self._direction == CommonScrollBar.DIR_HORIZENTAL then
		self._barBg:setPosition(cc.p(0, 0))
		self._pSlider:setPositionY(0)
	end
	self:updateSlider()
	self._touBg:addTouchEventListener(handler(self, self._onPageTouch))
end

function CommonScrollBar:onEnter()
	self:scheduleUpdateWithPriorityLua(handler(self, self._update), 0)
end

function CommonScrollBar:_onPageTouch(sender, state)
	if self._ratio >= 1 then
		return
	end
	if state == ccui.TouchEventType.began then
		return self:onTouchBegan(sender, state)
	elseif state == ccui.TouchEventType.moved then
		self:onTouchMoved(sender, state)
	elseif state == ccui.TouchEventType.ended or state == ccui.TouchEventType.canceled then
		self:onTouchEnded(sender, state)
	end
end

function CommonScrollBar:onExit()
end

function CommonScrollBar:_update(dt)
	if self._ratio >= 1 then
		return
	end
	local curContentSize = self._pTarget:getInnerContainerSize()
	if
		(not (math.abs(curContentSize.height - self._preContentSize.height) <= 0.00001) or
			not (math.abs(curContentSize.width - self._preContentSize.width) <= 0.00001))
	 then
		self._preContentSize = curContentSize
		self:updateSlider()
	end

	local bgSize = self._barBg:getContentSize()
	if self._direction == CommonScrollBar.DIR_VERTICAL then
		local curOffset =
			self:_posAdd(
			cc.p(self._pTarget:getInnerContainerPosition()),
			cc.p(
				self:_sizeSub(self._preContentSize, self._viewSize).width / 2,
				self:_sizeSub(self._preContentSize, self._viewSize).height / 2
			)
		)
		local ratio = curOffset.y / (self._viewSize.height * 0.5 - curContentSize.height * 0.5)
		ratio = math.abs(ratio) > 1 and ratio / math.abs(ratio) or ratio
		local sliderOffset = ratio * (bgSize.height * 0.5 - self._pSlider:getContentSize().height * 0.5)
		self._pSlider:setPositionY(sliderOffset)
	elseif self._direction == CommonScrollBar.DIR_HORIZENTAL then
		local curOffset =
			self:_posSub(
			cc.p(self._pTarget:getInnerContainerPosition()),
			cc.p(
				self:_sizeSub(self._preContentSize, self._viewSize).width / 2,
				self:_sizeSub(self._preContentSize, self._viewSize).height / 2
			)
		)
		local ratio = -curOffset.x / (self._viewSize.width - curContentSize.width)
		ratio = math.abs(ratio) > 1 and ratio / math.abs(ratio) or ratio
		local sliderOffset = ratio * (bgSize.width * 0.5 - self._pSlider:getContentSize().width * 0.5)
		self._pSlider:setPositionX(sliderOffset)
	end
end

function CommonScrollBar:_posAdd(pos1, pos2)
	return cc.p(pos1.x + pos2.x, pos1.y + pos2.y)
end

function CommonScrollBar:_posSub(pos1, pos2)
	return self:_posAdd(pos1, cc.p(-pos2.x, -pos2.y))
end

function CommonScrollBar:_sizeSub(size1, size2)
	return cc.size(size1.width - size2.width, size1.height - size2.height)
end

function CommonScrollBar:onTouchBegan(touch, pEvent)
	logWarn("CommonScrollBar:onTouchBegan")
	self._sliderCurPos = cc.p(self._pSlider:getPosition())
	self._targetCurPos = cc.p(self._pTarget:getInnerContainerPosition())
	local touchPoint = touch:getTouchBeganPosition()
	self._firstTouch = touchPoint
	--//将触摸点转为在当前子层下的坐标
	touchPoint = self:convertToNodeSpace(touchPoint)
	--//只响应点击了滑块背景的触摸
	local bgPos = cc.p(self._barBg:getPosition())
	local bgSize = self._barBg:getContentSize()
	local touchRect = cc.rect(bgPos.x - bgSize.width * 0.5, bgPos.y - bgSize.height * 0.5, bgSize.width, bgSize.height)
	if (not cc.rectContainsPoint(touchRect, touchPoint)) then
		return false
	end
	--//如果先点击了滑块，则设置标志
	local bgPos = cc.p(self._pSlider:getPosition())
	local bgSize = self._pSlider:getContentSize()
	local touchRect = cc.rect(bgPos.x - bgSize.width * 0.5, bgPos.y - bgSize.height * 0.5, bgSize.width, bgSize.height)
	if cc.rectContainsPoint(touchRect, touchPoint) then
		self._sliderTouched = true
		logWarn("CommonScrollBar:onTouchBegan 1")
	else --//如果没有点击滑块，则点击的是滑块背景图
		logWarn("CommonScrollBar:onTouchBegan 2")
		if self._direction == CommonScrollBar.DIR_VERTICAL then
			--//通过调整self._pTarget的偏移，从而调整了滑块slider的位置，因为update函数会一直监听self._pTarget的偏移
			local offset = touchPoint.y - self._sliderCurPos.y
			if (touchPoint.y <= 0) then
				offset = offset + self._pSlider:getContentSize().height / 2
			else
				offset = offset - self._pSlider:getContentSize().height / 2
			end
			local newOff =
				self._targetCurPos.y +
				offset / (self._pSlider:getContentSize().height - self._viewSize.height) *
					(self._preContentSize.height - self._viewSize.height)
			self._pTarget:setInnerContainerPosition(cc.p(0, newOff))
		elseif self._direction == CommonScrollBar.DIR_HORIZENTAL then
			local offset = touchPoint.x - self._sliderCurPos.x
			if touchPoint.x <= 0 then
				offset = offset + self._pSlider:getContentSize().width / 2
			else
				offset = offset + self._pSlider:getContentSize().width / 2
			end
			local newOff =
				self._targetCurPos.x +
				offset / (self._viewSize.width - self._pSlider:getContentSize().width) *
					(self._preContentSize.width - self._viewSize.width)
			self._pTarget:setInnerContainerPosition(cc.p(newOff, 0))
		end
	end
	return true
end

function CommonScrollBar:onTouchMoved(pTouch, pEvent)
	logWarn("CommonScrollBar:onTouchMoved")
	--//只响应点击了滑块的移动
	if (self._sliderTouched) then
		logWarn("CommonScrollBar:onTouchMoved 1")
		local touchPosition = pTouch:getTouchMovePosition()
		local offPos = cc.p(touchPosition.x - self._firstTouch.x, touchPosition.y - self._firstTouch.y)
		if (self._direction == CommonScrollBar.DIR_VERTICAL) then
			--//通过调整self._pTarget的偏移，从而调整了滑块slider的位置，因为update函数会一直监听self._pTarget的偏移
			local newOff = self._sliderCurPos.y + offPos.y
			--//判断滑块是否滑出界限
			if (math.abs(newOff) > (self._viewSize.height - self._pSlider:getContentSize().height) / 2) then
				newOff =
					(newOff < 0 and ((self._pSlider:getContentSize().height - self._viewSize.height) / 2) or
					((self._viewSize.height - self._pSlider:getContentSize().height) / 2))
			end
			newOff = newOff - self._sliderCurPos.y
			self._pTarget:setInnerContainerPosition(
				cc.p(
					0,
					self._targetCurPos.y +
						newOff / (self._pSlider:getContentSize().height - self._viewSize.height) *
							(self._preContentSize.height - self._viewSize.height)
				)
			)
		elseif (self._direction == CommonScrollBar.DIR_HORIZENTAL) then
			logWarn("CommonScrollBar:onTouchMoved 2")
			local newOff = self._sliderCurPos.x + offPos.x
			if (math.abs(newOff) > (self._viewSize.width - self._pSlider:getContentSize().width) / 2) then
				newOff =
					(newOff < 0 and ((self._pSlider:getContentSize().width - self._viewSize.width) / 2) or
					((self._viewSize.width - self._pSlider:getContentSize().width) / 2))
			end
			newOff = newOff - self._sliderCurPos.x
			self._pTarget:setInnerContainerPosition(
				cc.p(
					self._targetCurPos.x +
						newOff / (self._viewSize.width - self._pSlider:getContentSize().width) *
							(self._preContentSize.width - self._viewSize.width),
					0
				)
			)
		end
	end
end

function CommonScrollBar:onTouchEnded(pTouch, pEvent)
	logWarn("CommonScrollBar:onTouchEnded")
	self._sliderTouched = false
end

function CommonScrollBar:updateSlider()
	local bgSize = self._barBg:getContentSize()
	if (self._direction == CommonScrollBar.DIR_VERTICAL) then
		self._ratio = self._viewSize.height / self._preContentSize.height
		self._pSlider:setContentSize(cc.size(self._pSlider:getContentSize().width, bgSize.height * self._ratio))
	elseif (self._direction == CommonScrollBar.DIR_HORIZENTAL) then
		self._ratio = self._viewSize.width / self._preContentSize.width
		self._pSlider:setContentSize(cc.size(bgSize.width * self._ratio, self._pSlider:getContentSize().height))
	--//如果要显示的内容的尺寸比视图大小小，则隐藏滑块slider
	end
end

return CommonScrollBar
